﻿using System;
using System.Collections.Generic;
using System.IO;
using Visifire.Charts;
using VisualStock.Infrastructure.Models;

namespace VisualStock.Infrastructure.Converters
{
    public class HistoricalDataConverter
    {
        public static StockHistoricalDataCollection ConvertFromCSV(byte[] dataBytes)
        {
            using (MemoryStream ms = new MemoryStream(dataBytes))
            {
                return ConvertFromCSV(ms);
            }
        }

        /// <summary>
        /// Convert the specified string array(CSV format) to StockRealtimeDataCollection object
        /// </summary>
        public static StockHistoricalDataCollection ConvertFromCSV(Stream dataStream)
        {
            if (dataStream == null || dataStream.Length < 1)
            {
                return null;
            }

            // Read all the lines in the stream
            StreamReader reader = new StreamReader(dataStream);
            List<string> dataLines = new List<string>();
            while (!reader.EndOfStream)
                dataLines.Add(reader.ReadLine());

            int DateColumn = 0, OpenColumn = 1, HighColumn = 2, LowColumn = 3, CloseCloumn = 4, VolumnColumn = 5;

            // There is at least 1 row of the data in the file
            if (dataLines.Count <= 1) return null;
            else
            {
                // Verify the data format,the data must has at least 6 columns
                string[] subLines = dataLines[0].Split(',');
                if (subLines.Length < 6)
                {
                    return null;
                }
                else
                {
                    for (int j = 0; j < subLines.Length; j++)
                    {
                        if (subLines[j].Contains("Date")) DateColumn = j;
                        else if (subLines[j].Contains("Open")) OpenColumn = j;
                        else if (subLines[j].Contains("High")) HighColumn = j;
                        else if (subLines[j].Contains("Low")) LowColumn = j;
                        else if (subLines[j].Contains("Close")) CloseCloumn = j;
                        else if (subLines[j].Contains("Volume")) VolumnColumn = j;
                    }
                }

                // Analyse all data
                StockHistoricalDataCollection dataCollection = new StockHistoricalDataCollection();
                // Csv data is separated by ','
                const char SEPARATE_SYMBOL = ',';
                for (int i = 1; i < dataLines.Count; i++)
                {
                    string line = dataLines[i];
                    // Separate the data with the SEPARATE_SYMBOL
                    subLines = line.Split(SEPARATE_SYMBOL);
                    // Ignore the missing data
                    if (subLines.Length < 6) continue;
                    dataCollection.Add(
                        new StockHistoricalDataItem
                        {
                            QuoteDate = DateTime.Parse(subLines[DateColumn]),
                            OpeningPrice = double.Parse(subLines[OpenColumn]),
                            HighestPrice = double.Parse(subLines[HighColumn]),
                            LowestPrice = double.Parse(subLines[LowColumn]),
                            ClosingPrice = double.Parse(subLines[CloseCloumn]),
                            Volume = double.Parse(subLines[VolumnColumn])
                        });
                }
                return dataCollection;
            }
        }

        public static DataPointCollection ConvertToDataPointCollection(StockHistoricalDataCollection dataCollection)
        {
            DataPointCollection dpCollection = new DataPointCollection();
            foreach (StockHistoricalDataItem item in dataCollection)
            {
                dpCollection.Add(new DataPoint
                {
                    XValue = item.QuoteDate,
                    YValue = item.ClosingPrice,
                    YValues = new double[] { item.OpeningPrice, item.ClosingPrice, item.HighestPrice, item.LowestPrice },
                    ZValue = item.Volume
                });
            }
            return dpCollection;
        }
    }
}
